home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
ab20
/
ab20_archive
/
utilities
/
emulators
/
unixlib.lzh
/
socket.c
< prev
Wrap
C/C++ Source or Header
|
1991-10-22
|
11KB
|
482 lines
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <exec/types.h>
#include <exec/ports.h>
#include <stdio.h>
#include <errno.h>
#include <functions.h>
extern int errno;
char *malloc();
#define MAXSOCKET 20
static struct socket_entry {
int in_use;
char *to_client;
char *from_client;
} sockets[MAXSOCKET];
/* this structs must be used by telnet too */
struct connect_message {
struct Message Msg;
char *port_name;
};
struct data_message {
struct Message Msg;
char *buffer;
int length;
};
extern char *mktemp(char *);
/* For more info about this functions, consult an UNIX-manual */
int sowrite(int, char *, int);
int soread(int, char *, int);
int accept(int, struct sockaddr *, int *);
int socket( int, int, int);
int find_free_socket(void);
void soclose(int);
int setsockopt(int, int, int, char *, int);
int bind(int, struct sockaddr *, int);
int SafePutToPort(struct Message *, char *);
struct Message *SafeReadFromPort(char *);
/* functions which handle fd_sets are macro's, defined in sys/types.h
#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
#define FD_ZERO(p) bzero((char *)(p), sizeof (*(p)))
*/
void add_signal_to_fdset(n, p)
int n;
fd_set *p;
{
register char *portname;
register struct MsgPort *port;
if(!sockets[n].in_use)
return;
if(!(portname = sockets[n].from_client))
return;
if(!(port = FindPort(portname)))
return;
*p = *p | 1 << port->mp_SigBit;
return;
}
void delete_signal_from_fdset(n, p)
int n;
fd_set *p;
{
char *portname;
struct MsgPort *port;
ULONG signal;
fprintf(stderr, "FD_CLR\n");
if(!sockets[n].in_use) {
fprintf(stderr, "signal from unused socket %d taken\n", n);
return;
}
if(!(portname = sockets[n].from_client)) {
fprintf(stderr, "socket %d has no from_client port !\n",n);
return;
}
fprintf(stderr, "%s\n", portname);
if(!(port = FindPort(portname))) {
fprintf(stderr, "Could not find port %s\n", portname);
return;
}
signal = 1 << port->mp_SigBit;
fprintf(stderr, "signal(hex): %x\n", signal);
fprintf(stderr, "fdset (hex): %x\n", *p);
*p = (*p) & (~signal);
fprintf(stderr, "fdset (hex): %x\n", *p);
return;
}
int is_member_of_fdset(n, p)
int n;
register fd_set *p;
{
register char *portname;
register struct MsgPort *port;
register ULONG signal;
register int result;
if(!sockets[n].in_use) {
fprintf(stderr, "signal from unused socket %d taken\n", n);
return 0;
}
if(!(portname = sockets[n].from_client)) {
fprintf(stderr, "socket %d has no from_client port !\n",n);
return 0;
}
if(!(port = FindPort(portname))) {
fprintf(stderr, "Could not find port %s\n", portname);
return 0;
}
signal = 1 << port->mp_SigBit;
result = (*p) & signal;
return (result!=0);
}
shutdown(socket, number)
register int socket;
register int number;
{
char tmp[4];
tmp[0] = -1;
tmp[1] = -3;
tmp[2] = 1;
tmp[3] = '\0';
sowrite(socket, tmp, 3);
}
/* sowrite will write to the clientport
* the client must read from the clientport, and write to the serverport
* When we write a message to the other side, we wait for the reply
*/
int sowrite(socket, buffer, length)
int socket, length;
char *buffer;
{
register struct data_message *msg;
register struct MsgPort *waitport;
register ULONG signal;
register int i;
waitport = CreatePort(NULL, 0);
if(!waitport) {
fprintf(stderr, "Could not allocate waitport\n");
errno = EIO;
return -1;
}
if(!(msg = (struct data_message *) malloc(sizeof (struct data_message)) )) {
fprintf(stderr, "Could not allocate message\n");
errno = EIO;
return -1;
}
msg->Msg.mn_Node.ln_Type = NT_MESSAGE;
msg->Msg.mn_Length = sizeof(struct data_message);
msg->Msg.mn_ReplyPort = waitport;
msg->buffer = buffer;
msg->length = length;
if(!SafePutToPort( (struct Message*)msg, sockets[socket].to_client)) {
fprintf(stderr,"Could not find client-port\n");
errno = EIO;
length = -1;
}
else
{
signal = Wait( SIGBREAKF_CTRL_D | 1L << waitport->mp_SigBit);
if(signal & SIGBREAKF_CTRL_D ) {
errno = EIO;
fprintf(stderr, "sowrite : aborted waiting for reply\n");
DeletePort(waitport);
return -1;
}
errno = 0; /* NO ERROR */
}
free((char*) msg);
DeletePort(waitport);
return length;
}
int soread(socket, buffer, length)
int socket, length;
char *buffer;
{
register struct data_message *msg = NULL;
register struct MsgPort *port = NULL;
register int bufpos = 0; /* first free position in the buffer */
register int i,x;
/* If we get here, there must be a message
*/
if(!(port = FindPort(sockets[socket].from_client))) {
fprintf(stderr,"Could not find the port\n");
errno = EHOSTUNREACH;
return -1;
}
/* Yes, read the port !! */
while( msg = (struct data_message*) SafeReadFromPort(sockets[socket].from_client))
{ /* concatenate the received message to the buffer */
for(i=0;i<msg->length;i++)
buffer[bufpos+i] = msg->buffer[i];
ReplyMsg((struct Message *)msg); /* tell telnet we received it */
bufpos = bufpos+i;
}
if(bufpos == 0) {
fprintf(stderr, "soread : could not read any message !!\n");
errno = EMSGSIZE;
return -1;
}
return bufpos;
}
int accept(s, addr, addrlen)
int s;
struct sockaddr *addr;
int *addrlen;
{
register struct MsgPort *port;
register struct connect_message *msg;
register int new_socket;
register char *to_client;
register ULONG signal;
/* copy socket s to a new socket, and return the descriptor for the
* new socket-descriptor and fill in the addr en addrlen fields
*/
if(!sockets[s].in_use) {
fprintf(stderr, "socket %d is not in use !!!\n", s);
errno = EINTR;
return -1;
}
if(!(port = FindPort(sockets[s].from_client))) {
fprintf(stderr, "Could not find port\n");
return -1;
}
/* Allow 1 client, let the rest wait */
msg = (struct connect_message *) SafeReadFromPort(sockets[s].from_client);
if(!msg) {
errno = EWOULDBLOCK;
return -1;
}
new_socket = socket(0,0,0);
if(new_socket == -1) {
msg->port_name = NULL;
ReplyMsg((struct Message *)msg);
return -1;
}
/* store the port to which we must send data */
to_client = malloc(strlen(msg->port_name)+1);
strcpy(to_client, msg->port_name);
sockets[new_socket].to_client = to_client;
/* return the port to which we will listen */
msg->port_name = sockets[new_socket].from_client;
ReplyMsg((struct Message *) msg);
return new_socket;
}
int socket( domain, type, protocol)
int domain, type, protocol;
{
register struct MsgPort *port;
register int new_sd;
register char *name, *tmpname;
/* this code does not need Forbid()/Permit(), when you want to run 2 mud's,
you should add it :+)
*/
tmpname = mktemp("parserXXXXXXXX");
name = malloc(strlen(tmpname) + 1);
strcpy(name, tmpname);
if(!name) {
fprintf(stderr, "Could not create new port name\n");
return -1;
}
new_sd = find_free_socket();
if(new_sd == -1) {
errno = EMFILE;
return -1;
}
if((port = (struct MsgPort *) CreatePort(name, 0)) == NULL) {
errno = ENOBUFS;
return -1;
}
sockets[new_sd].from_client = name; /* we will listen to this name */
sockets[new_sd].to_client = NULL; /* will be filled in by accept() */
sockets[new_sd].in_use = 1;
return new_sd;
}
int find_free_socket()
{
register int entry = MAXSOCKET-1;
while(entry >= 0) {
if(sockets[entry].in_use == 0)
return entry;
entry--;
}
return -1;
}
void soclose(socket)
int socket;
{
register struct MsgPort *port;
/* I should check that this was the last reference to the socket */
if(socket < 0 || socket >= MAXSOCKET) {
fprintf(stderr, "failed to close socket %d\n", socket);
return;
}
if(!sockets[socket].in_use) {
fprintf(stderr, "failed to close socket %d\n", socket);
return;
}
port = FindPort(sockets[socket].from_client);
if(!port) {
fprintf(stderr,"tried to close non-existing port\n");
return;
}
DeletePort(port);
if(sockets[socket].from_client)
free(sockets[socket].from_client);
if(sockets[socket].to_client)
free(sockets[socket].to_client);
sockets[socket].from_client = NULL;
sockets[socket].to_client = NULL;
sockets[socket].in_use = 0;
}
int setsockopt(s, level, optname, optval, optlen)
int s, level, optname;
char *optval;
int optlen;
{
return 0;
}
int bind(s, name, namelen)
int s;
struct sockaddr *name;
int namelen;
{
register struct MsgPort *old_port, *new_port;
register char *port_name;
/* according to the manual, socket s should have no name yet, but
* it should get the name specified in name. So lets remove the old
* name, and replace it with a new one. The portname is specified as
* an unsigned int, but let's pretend it is a 32 bits number. We need
* 10 + 1 digits in the string, let's make that 20 and hope it's enough
*/
port_name = malloc(20);
sprintf(port_name, "%u", ((struct sockaddr_in *)name)->sin_port);
if(!sockets[s].in_use) {/* trying to bind a socket that's not in use */
fprintf(stderr, "Can't bind a free socket !\n");
return -1;
}
old_port = FindPort(sockets[s].from_client);
if(!old_port) {
fprintf(stderr, "Non-existing port\n");
return -1;
}
if(FindPort((char*)port_name) != NULL) { /* Each name must be unique */
fprintf(stderr, "Name must be unique\n");
errno = EADDRINUSE;
return -1;
}
/* Delete the old port, and create a new port with a name, no
checking for messages, cos I did not send any
*/
new_port = CreatePort(port_name,0);
if(!new_port) {
fprintf(stderr, "failed to create new socket\n");
return -1;
}
/* delete the old port */
soclose(s);
sockets[s].from_client = port_name;
sockets[s].to_client = NULL; /* no replyport !! */
sockets[s].in_use = 1;
return 0;
}
int listen(s, backlog)
int s, backlog;
{
return 0;
}
int SafePutToPort(message, portname)
struct Message *message;
char * portname;
{
register struct MsgPort *port;
Forbid();
port = FindPort(portname);
if(port)
PutMsg(port, message);
Permit();
if(port) {
errno = 0;
return 1;
}
else
{
errno = EIO;
return 0;
}
}
struct Message *SafeReadFromPort(portname)
char * portname;
{
register struct MsgPort *port;
register struct Message *msg;
Forbid();
port = FindPort(portname);
if(port)
msg = GetMsg(port);
Permit();
if(port)
{
errno = 0;
return msg;
}
else
{
errno = EIO;
return NULL;
}
}